package cn.mw.cmdb.processor;

import cn.mw.cmdb.entity.*;
import cn.mw.cmdb.param.InstanceSearchParam;
import cn.mw.cmdb.param.TableSearchParam;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.CustomModelServiceImpl;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.cmdb.viewProcessor.RelateDataViewProcessor;
import cn.mw.cmdb.viewProcessor.ViewProcessorManage;
import cn.mw.microMonitorCommon.api.common.Constants;
import cn.mw.microMonitorCommon.entity.cmdb.RelatedDataType;
import cn.mw.microMonitorCommon.entity.cmdb.TableHeaderItem;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

import static cn.mw.cmdb.processor.TableDataFactory.createTableHeaderId;
import static cn.mw.microMonitorCommon.entity.cmdb.TableHeaderItem.flexNum;

/**
 * 模型实例自定义字段属性Processor
 */
public class StaticsProcessorCustomInstance implements TableDataProccessor {

    private CmdbServiceManage cmdbServiceManage;

    private TableSearchParam tableDataParam;

    public StaticsProcessorCustomInstance(CmdbServiceManage cmdbServiceManage, TableSearchParam tableDataParam) {
        this.cmdbServiceManage = cmdbServiceManage;
        this.tableDataParam = tableDataParam;
    }

    @Override
    public List genData(TableDataProcessorContext context) throws Exception {
        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        InstanceSearchParam instanceSearchParam = new InstanceSearchParam();
        String[] assetStateQuery = null;
        String modelId = tableDataParam.getId();
        if (tableDataParam.getId().contains(Constants.ID_SPLIT)) {
            modelId = tableDataParam.getId().split(Constants.ID_SPLIT)[0];
            assetStateQuery = tableDataParam.getId().split(Constants.ID_SPLIT)[1].split(Constants.PROPERTY_SPLIT);
        }
        PropertyUtils.copyProperties(instanceSearchParam, tableDataParam);
        instanceSearchParam.setModelId(modelId);
        if (assetStateQuery != null) {
            Map<String, Object> searchData = new HashMap<>();
            if (assetStateQuery.length > 1) {
                searchData.put(assetStateQuery[0], assetStateQuery[1]);
            } else {
                searchData.put(assetStateQuery[0], null);
            }
            instanceSearchParam.setData(searchData);
        }
        if(tableDataParam.isEnableMonitorStatus()){
            //查询资产状态
            instanceSearchParam.setEnableMonitorStatus(true);
        }
        //不分页查询,为了排序
        //instanceSearchParam.setPage(null);
        List<InstanceInfoExtend> instanceInfos = instanceService.aggregateList(instanceSearchParam);

        List<Map> ret = new ArrayList<>();
        ViewProcessorManage processorManage = new ViewProcessorManage();

        List<TableHeaderItem> tableHeaderItems = context.getTableHeaderItems();
        if (null != instanceInfos && null != tableHeaderItems) {
            Set<RelateDataViewProcessor> relateDataViewProcess = processorManage.buildRelateDataViewProcessor(tableHeaderItems);
            Map<? extends Class<? extends RelateDataViewProcessor>, List<RelateDataViewProcessor>> collect = relateDataViewProcess.stream().collect(Collectors.groupingBy(s -> s.getClass()));
            Set<RelateDataViewProcessor> relateDataViewProcessors = new HashSet<>();
            collect.forEach((k,v)->{
                if(v!=null && v.size()>0){
                    RelateDataViewProcessor relateDataViewProcessor = v.get(0);
                    relateDataViewProcessors.add(relateDataViewProcessor);
                }
            });
            //初始化
            int seq = 0;
            for (InstanceInfoExtend instanceInfo : instanceInfos) {
                seq++;
                Map data = new LinkedHashMap();
                if (tableDataParam.isShowAllField()) {
                    Map<String, Object> dataMap = instanceInfo.getData();
                    data.putAll(dataMap);
                }
                for (TableHeaderItem item : tableHeaderItems) {
                    Object value = instanceInfo.getValue(item.getField());
                    data.put(item.getField(), value);
                }
                data.put(CMDBTool.getFieldName(InstanceInfoExtend::getModelName),instanceInfo.getModelName());
                data.put(CMDBTool.getFieldName(InstanceInfoExtend::getModelGroupName), instanceInfo.getModelGroupName());
                data.put(CMDBTool.getFieldName(InstanceInfoExtend::getModelId), instanceInfo.getModelId());
                data.put(CMDBTool.getFieldName(InstanceInfoExtend::getFinanceParentId), instanceInfo.getFinanceParentId());
                data.put(CMDBTool.getFieldName(InstanceInfoExtend::getGroupId), instanceInfo.getGroupId());ret.add(data);
                //data.put(SEQ, seq);

                if (null == relateDataViewProcessors || relateDataViewProcessors.size() == 0) {
                    continue;
                }
                for (RelateDataViewProcessor processor : relateDataViewProcessors) {
                    processor.init(instanceInfo, data);
                }
            }

            if (null == relateDataViewProcessors || relateDataViewProcessors.size() == 0) {
                return ret;
            }
            //查询关联数据
            for (RelateDataViewProcessor processor : relateDataViewProcessors) {
                processor.selectRelateData(context);
            }

            //设置关联数据
            for (Map m : ret) {
                for (RelateDataViewProcessor processor : relateDataViewProcessors) {
                    processor.setRelateData(m);
                }
            }
        }
        return ret;
    }

    @Override
    public List<TableHeaderItem> genDefaultTableHeader(Class clazz) throws Exception {
        List<TableHeaderItem> tableHeaderItems = new ArrayList<>();
        //根据modelId获取当前模型所对应的全部属性
        CustomModelServiceImpl modelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
        Object modelId = tableDataParam.getId();
        // 自定义分类场景，状态节点 id由上级id+资产状态组成 id由属性名:属性值拼接而成
        if (tableDataParam.getId().contains(Constants.ID_SPLIT)) {
            modelId = tableDataParam.getId().split(Constants.ID_SPLIT)[0];
        }
        ModelInfo modelInfo = modelService.doSelectById(modelId);
        //将属性按照显示权限过滤（勾选列表显示的），转换为List<TableHeaderItem>放回
        //按照属性信息来循环处理,保证只会输入模型中定义的属性
        for (PropertyInfo propertyInfo : modelInfo.getPropertyInfoList()) {
            Set<FieldViewAuthType> fieldViewAuthTypes = propertyInfo.getFieldViewAuthTypes();
            //获取所有列表显示的字段属性
            if (null != fieldViewAuthTypes && fieldViewAuthTypes.contains(FieldViewAuthType.list)) {
                TableHeaderItem item = new TableHeaderItem();
                ForeignKey foreignKey = propertyInfo.getForeignKey();
                if (null == foreignKey || !StringUtils.hasText(foreignKey.getKeyName())) {
                    item = new TableHeaderItem();
                } else {
                    RelatedDataType relatedDataType = RelatedDataType.valueOf(foreignKey.getRelatedDataType());
                    item = TableHeaderItemExt.build().keyName(foreignKey.getKeyName());
                    item.setParseType(relatedDataType);
                }
                item.setField(propertyInfo.getId());
                item.setHeaderName(propertyInfo.getName());
                item.setVisible(true);
                item.setFlex(flexNum);
                item.setPropertyTypeId(propertyInfo.getPropertyTypeRef().getTypeId());
                tableHeaderItems.add(item);
            }
        }
        createTableHeaderId(tableHeaderItems);
        return tableHeaderItems;
    }
}
